﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using MindFusion.Diagramming;
using System.IO;

namespace Inference
{
	public class Settings
	{
		public Settings(TreeView tv, Diagram d)
		{
			TargetTreeView = tv;
			TargetDiagram = d;
			TreeViewHighlighters = new List<Highlighter>();


			//Parent, IS_A
			TreeViewHighlighters.Add
				(new Highlighter
					(TargetNodesGroups.Parent,
					Color.Gray,
					TargetTreeView.BackColor,
					TargetDiagram.BackBrush,
					"Подсветка фрейма, являющегося родителем выбранного фрейма",
					true,
					new GetTargetsMethod(GetParent),
					new ConvertTargetsMethod(GetDiagramNodesFromTreeNodes)
				));
			//-is_a
			TreeViewHighlighters.Add
				(new Highlighter
					(TargetNodesGroups.Children,
					Color.LightPink,
					TargetTreeView.BackColor,
					TargetDiagram.BackBrush,
					"Подсветка фреймов, являющихся потомками текущего фрейма",
					true,
					new GetTargetsMethod(GetChildren),
					new ConvertTargetsMethod(GetDiagramNodesFromTreeNodes)
				));
			//brothers
			TreeViewHighlighters.Add
				(new Highlighter
					(TargetNodesGroups.Brothers,
					Color.LightBlue,
					TargetTreeView.BackColor,
					TargetDiagram.BackBrush,
					"Подсветка фреймов, имеющих общего с выбранным фреймом фрейма-родителя",
					false,
					new GetTargetsMethod(GetBrothers),
					new ConvertTargetsMethod(GetDiagramNodesFromTreeNodes)
				));
			//next
			TreeViewHighlighters.Add
				(new Highlighter
					(TargetNodesGroups.Next,
					Color.LightGreen,
					TargetTreeView.BackColor,
					TargetDiagram.BackBrush,
					"Подсветка фрейма, указанного в слоте Next выбранного фрейма",
					true,
					new GetTargetsMethod(GetNext),
					new ConvertTargetsMethod(GetDiagramNodesFromTreeNodes)
				));
			//previous
			TreeViewHighlighters.Add
				(new Highlighter
					(TargetNodesGroups.Previous,
					Color.Red,
					TargetTreeView.BackColor,
					TargetDiagram.BackBrush,
					"Подсветка фрейма, в слоте Next которого указан выбранный фрейм",
					false,
					new GetTargetsMethod(GetPrevious),
					new ConvertTargetsMethod(GetDiagramNodesFromTreeNodes)
				));
			//subs
			TreeViewHighlighters.Add
				(new Highlighter
					(TargetNodesGroups.Sub,
					Color.Gold,
					TargetTreeView.BackColor,
					TargetDiagram.BackBrush,
					"Подсветка субфреймов выбранного фрейма",
					true,
					new GetTargetsMethod(GetSubs),
					new ConvertTargetsMethod(GetDiagramNodesFromTreeNodes)
				));
			//users
			TreeViewHighlighters.Add
				(new Highlighter
					(TargetNodesGroups.SubUser,
					Color.Magenta,
					TargetTreeView.BackColor,
					TargetDiagram.BackBrush,
					"Подсветка фреймов, для которых выбранный фрейм является субфреймом",
					false,
					new GetTargetsMethod(GetUsers),
					new ConvertTargetsMethod(GetDiagramNodesFromTreeNodes)
				));
			//Domains
			TreeViewHighlighters.Add
				(new Highlighter
					(TargetNodesGroups.Domains,
					Color.Orange,
					TargetTreeView.BackColor,
					TargetDiagram.BackBrush,
					"Подсветка доменов слотов выбранного фрейма",
					false,
					new GetTargetsMethod(GetDomains),
					new ConvertTargetsMethod(GetDiagramNodesFromTreeNodes)
				));
			//DomainUsers
			TreeViewHighlighters.Add
				(new Highlighter
					(TargetNodesGroups.DomainUsers,
					Color.RosyBrown,
					TargetTreeView.BackColor,
					TargetDiagram.BackBrush,
					"Подсветка фреймов, некоторые слоты которых относятся к выбранному домену",
					false,
					new GetTargetsMethod(GetDomainUsers),
					new ConvertTargetsMethod(GetDiagramNodesFromTreeNodes)
				));
		}

		public void LoadDefault()
		{
			LinksSettings = new _LinksSettings();
			LinksSettings.ColorISA = Color.Gray;
			LinksSettings.ColorNEXT = Color.Green;
			LinksSettings.ColorSUB = Color.Magenta;
			LinksSettings.ShowISA = true;
			LinksSettings.ShowNEXT = true;
			LinksSettings.ShowSUB = false;
		}

		public bool LoadFromFile()
		{
			try
			{
				LinksSettings = new _LinksSettings();
				string[] par = null;
				StreamReader sr = new StreamReader("preferences.cfg");
				foreach (Highlighter h in TreeViewHighlighters)
				{
					par = sr.ReadLine().Split(';');
					h.Enabled = bool.Parse(par[0]);
					h.HighlightColor = Color.FromArgb
						(
							int.Parse(par[1]),
							int.Parse(par[2]),
							int.Parse(par[3]),
							int.Parse(par[4])
						);
				}
				par = sr.ReadLine().Split(';');
				LinksSettings.ShowISA = bool.Parse(par[0]);
				LinksSettings.ColorISA = Color.FromArgb
					(
						int.Parse(par[1]),
						int.Parse(par[2]),
						int.Parse(par[3]),
						int.Parse(par[4])
					);

				par = sr.ReadLine().Split(';');
				LinksSettings.ShowNEXT = bool.Parse(par[0]);
				LinksSettings.ColorNEXT = Color.FromArgb
					(
						int.Parse(par[1]),
						int.Parse(par[2]),
						int.Parse(par[3]),
						int.Parse(par[4])
					);

				par = sr.ReadLine().Split(';');
				LinksSettings.ShowSUB = bool.Parse(par[0]);
				LinksSettings.ColorSUB = Color.FromArgb
					(
						int.Parse(par[1]),
						int.Parse(par[2]),
						int.Parse(par[3]),
						int.Parse(par[4])
					);
				sr.Close();
				return true;
			}
			catch
			{
				return false;
			}
		}

		public void SaveToFile()
		{
			Color color = Color.AliceBlue;
			bool enabled = true;
			StreamWriter sw = new StreamWriter("preferences.cfg");
			foreach (Highlighter h in TreeViewHighlighters)
			{
				color = h.HighlightColor;
				enabled = h.Enabled;
				sw.WriteLine(string.Format("{0};{1};{2};{3};{4}",
					enabled.ToString(),
					color.A.ToString(),
					color.R.ToString(),
					color.G.ToString(),
					color.B.ToString()));
			}
			color = LinksSettings.ColorISA;
			enabled = LinksSettings.ShowISA;
			sw.WriteLine(string.Format("{0};{1};{2};{3};{4}",
				enabled.ToString(),
				color.A.ToString(),
				color.R.ToString(),
				color.G.ToString(),
				color.B.ToString()));

			color = LinksSettings.ColorNEXT;
			enabled = LinksSettings.ShowNEXT;
			sw.WriteLine(string.Format("{0};{1};{2};{3};{4}",
				enabled.ToString(),
				color.A.ToString(),
				color.R.ToString(),
				color.G.ToString(),
				color.B.ToString()));

			color = LinksSettings.ColorSUB;
			enabled = LinksSettings.ShowSUB;
			sw.WriteLine(string.Format("{0};{1};{2};{3};{4}",
				enabled.ToString(),
				color.A.ToString(),
				color.R.ToString(),
				color.G.ToString(),
				color.B.ToString()));
			sw.Flush();
			sw.Close();
		}

		#region get* funcs
		public List<TreeNode> GetChildren(TreeNode current)
		{
			List<TreeNode> res = new List<TreeNode>();
			if (current.Level == 2 && GetTreeNodeRoot(current).Text != "Домены")
			{
				foreach (TreeNode tn in FrameNodes)
				{
					if (tn.Nodes[1].Text.StartsWith("IS_A:"))
					{
						string parentName = tn.Nodes[1].Text.Substring(6);
						if (parentName == current.Text)
						{
							res.Add(tn);
						}
					}
				}
			}
			return res;
		}
		public List<TreeNode> GetParent(TreeNode current)
		{
			List<TreeNode> res = new List<TreeNode>();
			if (current.Level == 2 && GetTreeNodeRoot(current).Text != "Домены")
			{
				if (current.Nodes.Count > 0)
					if (current.Nodes[1].Text.StartsWith("IS_A:"))
					{
						string parentName = current.Nodes[1].Text.Substring(6);
						foreach (TreeNode tn in FrameNodes)
						{
							if (parentName == tn.Text)
							{
								res.Add(tn);
								break;
							}
						}
					}
			}
			//else
			//if (current.Level == 1 && current.Parent.Text == "Домены")
			//{
			//    Domains par = DomainHierarchier.GetParent(current.Text, new TaleEntities());
			//    if (par != null)
			//    {
			//        string pn = par.Name;
			//        foreach (TreeNode item in DomainNodes)
			//        {
			//            if (item.Text == pn)
			//            {
			//                res.Add(item);
			//                break;
			//            }
			//        }
			//    }
			//}
			return res;
		}
		public List<TreeNode> GetBrothers(TreeNode current)
		{
			List<TreeNode> res = new List<TreeNode>();
			if (GetTreeNodeRoot(current).Text != "Домены")
			{
				if (current.Level == 2)
				{
					List<TreeNode> pn = GetParent(current);
					if (pn.Count != 0)
					{
						res = GetChildren(pn[0]);
						res.Remove(current);
					}
					else
					{
					}
				}
			}
			return res;
		}
		public List<TreeNode> GetNext(TreeNode current)
		{
			List<TreeNode> res = new List<TreeNode>();
			if (current.Level == 2 && GetTreeNodeRoot(current).Text != "Домены")
			{
				if (current.Nodes.Count > 0)
				{
					foreach (TreeNode tn in current.Nodes)
					{
						if (tn.Text.ToLower() == "next")
						{
							string nextName = tn.Nodes[1].Text.Substring(20);
							if (nextName != "NULL")
								foreach (TreeNode stn in SituationNodes)
								{
									if (stn.Text == nextName)
									{
										res.Add(stn);
										break;
									}
								}
							break;
						}
					}
				}

			}
			return res;
		}
		public List<TreeNode> GetPrevious(TreeNode current)
		{
			List<TreeNode> res = new List<TreeNode>();
			if (current.Level == 2 && GetTreeNodeRoot(current).Text != "Домены")
			{
				if (current.Nodes.Count > 0)
				{
					bool done = false;
					foreach (TreeNode tn in SituationNodes)
					{
						foreach (TreeNode stn in tn.Nodes)
						{
							if (stn.Text.ToLower() == "next")
							{
								string nextName = stn.Nodes[1].Text.Substring(20);
								if (nextName == current.Text)
								{
									res.Add(tn);
									done = true;
									break;
								}
							}
						}
						if (done)
							break;
					}
				}

			}
			return res;
		}
		public List<TreeNode> GetSubs(TreeNode current)
		{
			List<TreeNode> res = new List<TreeNode>();
			if (current.Level == 2 && GetTreeNodeRoot(current).Text != "Домены")
			{
				if (current.Nodes.Count > 0)
				{
					List<string> subNames = new List<string>();
					foreach (TreeNode stn in current.Nodes)
					{
						if (stn.Nodes.Count != 0)
						{
							string domName = stn.Nodes[0].Text.Substring(7);
							bool isSub = false;
							foreach (TreeNode tn in FrameNodes)
							{
								if (tn.Text == domName)
								{
									isSub = true;
									break;
								}
							}

							if (isSub)
							{
								string subVal = stn.Nodes[1].Text.Substring(20);
								if (subVal != "NULL")
									subNames.Add(subVal);
							}
						}
					}
					foreach (TreeNode tn in EntityNodes)
					{
						if (subNames.Contains(tn.Text))
						{
							res.Add(tn);
							subNames.Remove(tn.Text);
						}
						if (subNames.Count == 0)
							break;
					}
				}

			}
			return res;
		}
		public List<TreeNode> GetUsers(TreeNode current)
		{
			List<TreeNode> res = new List<TreeNode>();
			if (current.Level == 2 && GetTreeNodeRoot(current).Text != "Домены")
			{
				if (current.Parent.Text == "Сущности")
				{
					if (current.Nodes.Count > 0)
					{
						foreach (TreeNode tn in FrameNodes)
						{
							foreach (TreeNode stn in tn.Nodes)
							{
								if (stn.Nodes.Count != 0)
								{
									string subVal = stn.Nodes[1].Text.Substring(20);
									if (subVal == current.Text)
									{
										res.Add(tn);
										break;
									}
								}
							}
						}
					}
				}
			}
			return res;
		}
		public List<TreeNode> GetDomains(TreeNode current)
		{
			List<TreeNode> res = new List<TreeNode>();
			if (GetTreeNodeRoot(current).Text != "Домены")
			{
				if (current.Level == 2)
				{
					if (current.Nodes.Count > 0)
					{
						List<string> domainsNames = new List<string>();
						foreach (TreeNode stn in current.Nodes)
						{
							if (stn.Nodes.Count != 0)
								domainsNames.Add(stn.Nodes[0].Text.Substring(7));
						}
						foreach (TreeNode tn in DomainNodes)
						{
							if (domainsNames.Contains(tn.Text))
							{
								res.Add(tn);
								domainsNames.Remove(tn.Text);
							}
							if (domainsNames.Count == 0)
								break;
						}
					}
				}
				if (current.Level == 3)
				{
					string domainName = "";
					if (current.Nodes.Count != 0)
					{
						domainName = current.Nodes[0].Text.Substring(7);
					}
					else
						if (current.Parent.Parent.Text == "Ситуации")
						{
							domainName = "Имена фреймов-ситуаций";
						}
						else
							if (current.Parent.Parent.Text == "Сущности")
							{
								domainName = "Имена фреймов-сущностей";
							}
					if (domainName != "")
						foreach (TreeNode tn in DomainNodes)
						{
							if (tn.Text == domainName)
							{
								res.Add(tn);
								break;
							}
						}
				}
			}
			return res;
		}

		public TreeNode GetTreeNodeRoot(TreeNode cur)
		{
			TreeNode tmp = cur;
			while (tmp.Level > 0)
			{
				tmp = tmp.Parent;
			}
			return tmp;
		}

		public List<TreeNode> GetDomainUsers(TreeNode current)
		{
			List<TreeNode> res = new List<TreeNode>();
			if (GetTreeNodeRoot(current).Text == "Домены")
			{
				string domainName = current.Text;
				if (domainName == "Имена фреймов-ситуаций")
				{
					foreach (TreeNode tn in SituationNodes)
					{
						res.Add(tn);
						res.Add(tn.Nodes[0]);
						res.Add(tn.Nodes[1]);
					}
				}
				else
					if (domainName == "Имена фреймов-сущностей")
					{
						foreach (TreeNode tn in EntityNodes)
						{
							res.Add(tn);
							res.Add(tn.Nodes[0]);
							res.Add(tn.Nodes[1]);
						}
					}
					else
						foreach (TreeNode tn in FrameNodes)
						{
							foreach (TreeNode stn in tn.Nodes)
							{
								if (stn.Nodes.Count != 0)
								{
									if (stn.Nodes[0].Text.Substring(7) == domainName)
									{
										if (!res.Contains(tn))
											res.Add(tn);
										res.Add(stn);
									}
								}
							}
						}

			}
			return res;
		}
		public List<TreeViewNode> GetDiagramNodesFromTreeNodes(List<TreeNode> source)
		{
			List<TreeViewNode> res = new List<TreeViewNode>();
			List<string> tnNames = new List<string>();
			foreach (TreeNode tn in source)
			{
				tnNames.Add(tn.Text);
			}
			foreach (DiagramNode dn in TargetDiagram.Nodes)
			{
				TreeViewNode tvn = ((TreeViewNode)dn);
				if (tnNames.Contains(tvn.Caption))
				{
					res.Add(tvn);
					tnNames.Remove(tvn.Caption);
				}
				if (tnNames.Count == 0)
					break;
			}
			return res;
		}
		#endregion

		public List<TreeNode> FrameNodes
		{
			get
			{
				List<TreeNode> res = new List<TreeNode>();
				foreach (TreeNode item in TargetTreeView.Nodes[0].Nodes[0].Nodes)
				{
					res.Add(item);
				}
				foreach (TreeNode item in TargetTreeView.Nodes[0].Nodes[1].Nodes)
				{
					res.Add(item);
				}
				return res;
			}
		}
		public TreeNodeCollection SituationNodes
		{
			get
			{
				return TargetTreeView.Nodes[0].Nodes[0].Nodes;
			}
		}
		public TreeNodeCollection EntityNodes
		{
			get
			{
				return TargetTreeView.Nodes[0].Nodes[1].Nodes;
			}
		}
		//public TreeNodeCollection DomainValuesNodes
		//{
		//    get
		//    {
		//        TreeNode tn = new TreeNode();
		//        tn.Nodes.AddRange(FindLeaves(TargetTreeView.Nodes[1]).ToArray());
		//        return tn.Nodes;
		//    }
		//}
		//public TreeNodeCollection DomainNodes
		//{
		//    get
		//    {
		//        TreeNode tn = new TreeNode();
		//        var qq = FindNotLeaves(TargetTreeView.Nodes[1]);
		//        var arr = qq.ToArray().di;
		//        //tn.Nodes.AddRange();
		//        return tn.Nodes;
		//    }
		//}

		public List<TreeNode> DomainNodes
		{
			get
			{
				return FindNotLeaves(TargetTreeView.Nodes[1]);
			}
		}

		public List<TreeNode> FindLeaves(TreeNode root)
		{
			List<TreeNode> res = new List<TreeNode>();
			foreach (TreeNode item in root.Nodes)
			{
				if (item.Nodes.Count == 0)
				{
					res.Add(item);
				}
				else
				{
					res.AddRange(FindLeaves(item));
				}
			}
			return res;
		}
		public List<TreeNode> FindNotLeaves(TreeNode root)
		{
			List<TreeNode> res = new List<TreeNode>();
			foreach (TreeNode item in root.Nodes)
			{
				if (item.Nodes.Count != 0)
				{
					res.Add(item);
					res.AddRange(FindNotLeaves(item));
				}
			}
			return res;
		}

		public TreeView TargetTreeView
		{
			get;
			set;
		}
		public Diagram TargetDiagram
		{
			get;
			set;
		}
		public List<Highlighter> TreeViewHighlighters
		{
			get;
			set;
		}
		public _LinksSettings LinksSettings
		{
			get;
			set;
		}

		public class _LinksSettings
		{
			public _LinksSettings()
			{
			}

			public Color ColorISA
			{
				get;
				set;
			}
			public Color ColorNEXT
			{
				get;
				set;
			}
			public Color ColorSUB
			{
				get;
				set;
			}

			public bool ShowISA
			{
				get;
				set;
			}
			public bool ShowNEXT
			{
				get;
				set;
			}
			public bool ShowSUB
			{
				get;
				set;
			}
		}
	}
}
